package com.ruoyi.iot.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.iot.channel.SynchroniseMessage;
import com.ruoyi.iot.channel.platform.PlatformMessageServiceImpl;
import com.ruoyi.iot.controller.IotDeviceController;
import com.ruoyi.iot.domain.IotCmd;
import com.ruoyi.iot.domain.IotDevice;
import com.ruoyi.iot.domain.vo.DevCmdVo;
import com.ruoyi.iot.domain.vo.UserOperateVO;
import com.ruoyi.iot.domain.vo.enums.ECodeEnum;
import com.ruoyi.iot.domain.vo.enums.EPlatformCmdType;
import com.ruoyi.iot.domain.vo.enums.ESponsor;
import com.ruoyi.iot.exchange.network.tcp.TcpNetty;
import com.ruoyi.iot.exchange.network.tcp.cache.TcpChannelCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class IotDeviceOperationImpl {



    /**
     * 加锁，把异步信息变为同步消息
     */
    @Autowired
    private SynchroniseMessage synchroniseMessage;

    /**
     * 项目服务
     */
    @Autowired
    private IotProjectServiceImpl projectService;




    /**
     * 产品服务
     */
    @Autowired
    private IotCmdServiceImpl iotCmdService;

    /**
     * 平台消息转换
     */
    @Autowired
    private PlatformMessageServiceImpl platformMessageService;

    /**
     * 设备操作指令
     */
    @Autowired
    IotDeviceServiceImpl iotDeviceService;


    /**
     * 生产用户的操作数据，用来包装交互结果
     * @param devCmdVo 指令操作对象
     * @return 返回结果
     */
    public UserOperateVO produceUserOperate(DevCmdVo devCmdVo) {
        UserOperateVO operateVO = new UserOperateVO();
        operateVO.setSuccess(false);
        String devId =  devCmdVo.getDevId();
        IotDevice iotDeviceCondition = new IotDevice();
        iotDeviceCondition.setDevId(devId);
        List<IotDevice> iotDeviceDos = iotDeviceService.selectIotDeviceList(iotDeviceCondition);
        if(iotDeviceDos.size() == 0) {
            operateVO.setMessage(ECodeEnum.IllegalDevice.getMsg());
            operateVO.setCode(ECodeEnum.IllegalDevice.getCode());
            operateVO.setSuccess(false);
            log.info(String.format("devId:%s not found!",devId));
            return operateVO;
        }
        IotDevice iotDeviceDo = iotDeviceDos.get(0);
        Long projectId = iotDeviceDo.getProjectId();
        if(projectId == null || projectService.selectIotProjectById(projectId) == null) {
            operateVO.setMessage(ECodeEnum.NotFindProduct.getMsg());
            operateVO.setCode(ECodeEnum.NotFindProduct.getCode());
            operateVO.setSuccess(false);
            log.info(String.format("devId:%s not belong any product!",projectId));
            return operateVO;
        }
        log.info("devCmd:" + JSON.toJSONString(devCmdVo));
        IotCmd iotCmdDo = iotCmdService.selectIotCmdById(devCmdVo.getCmdId());
        if(iotCmdDo == null) {
            log.info("not find this cmd!");
            operateVO.setCode(ECodeEnum.NotFindCmd.getCode());
            operateVO.setMessage(ECodeEnum.NotFindCmd.getMsg());
            operateVO.setSuccess(false);
            return operateVO;
        }
        if(iotCmdDo.getSponsor() != ESponsor.platform.getValue()) {
            operateVO.setCode(ECodeEnum.SponsorError.getCode());
            operateVO.setMessage(ECodeEnum.SponsorError.getMsg());
            operateVO.setSuccess(false);
            return operateVO;
        }

        String devCode = devCmdVo.getDevId();

        Boolean rst = TcpChannelCache.getChannel(devCode) == null;
        if(rst) {
            log.info(String.format("device:%s offline",devCmdVo.getDevId()));
            operateVO.setSuccess(false);
            operateVO.setCode(ECodeEnum.DeviceOffline.getCode());
            operateVO.setMessage(ECodeEnum.DeviceOffline.getMsg());
            return operateVO;
        }

        EPlatformCmdType platformCmdType = EPlatformCmdType.getType(iotCmdDo.getCmdType().intValue());
        log.info(String.format("device:%s cmdType:%s data:%s",devCmdVo.getDevId(),platformCmdType.toString(), JSON.toJSONString(devCmdVo)));
        if(platformCmdType == EPlatformCmdType.CMD) {
            DevCmdVo resultDTO = platformMessageService.platformCmd(devCmdVo);
            if (resultDTO != null) {
                operateVO.setData(resultDTO);
                operateVO.setCode(ECodeEnum.Success.getCode());
                operateVO.setMessage(ECodeEnum.Success.getMsg());
                operateVO.setSuccess(true);
                return operateVO;
            }
        }
        if(platformCmdType == EPlatformCmdType.NOTICE ) {
            platformMessageService.platformNotify(devCmdVo);
            operateVO.setCode(ECodeEnum.Success.getCode());
            operateVO.setMessage(ECodeEnum.Success.getMsg());
            operateVO.setSuccess(true);
            return operateVO;
        }

        if(platformCmdType == EPlatformCmdType.RESULT ) {
            synchroniseMessage.notifyPlatformMessage(devCmdVo.getDevId()
                    ,devCmdVo.getCmdId(),devCmdVo);
            operateVO.setCode(ECodeEnum.Success.getCode());
            operateVO.setMessage(ECodeEnum.Success.getMsg());
            operateVO.setSuccess(true);
            return operateVO;
        }
        //如果回复容器里面没有对应的key，则是通知
        if(platformCmdType == EPlatformCmdType.NOTICE_OR_RESULT) {
            rst = synchroniseMessage.notifyPlatformMessage(devCmdVo.getDevId()
                    ,iotCmdDo.getResultId(),devCmdVo);
            if(!rst) {
                platformMessageService.platformNotify(devCmdVo);
            }
            operateVO.setCode(ECodeEnum.Success.getCode());
            operateVO.setMessage(ECodeEnum.Success.getMsg());
            operateVO.setSuccess(true);
            return operateVO;
        }

        return  operateVO;
    }



}
